package lumis.service.resourcescheduler;

import java.util.Collection;
import java.util.Locale;

import org.hibernate.Session;

import lumis.doui.render.IRenderable;
import lumis.doui.render.IRenderer;
import lumis.doui.source.field.type.AbstractSourceFieldDataType;
import lumis.portal.PortalException;
import lumis.portal.dao.DaoException;
import lumis.portal.dao.hibernate.ITransactionHibernate;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.util.XmlUtil;
import lumis.util.converter.AbstractConverter;
import lumis.util.converter.ConversionException;
import lumis.util.converter.IConverter;
import lumis.util.converter.UnsupportedConversionTypeException;
import lumis.util.query.QueryFieldTypes;

/**
 * A resources data type. Its value is a list of resources stored.
 *
 * @version $Revision: 9027 $ $Date: 2008-03-13 17:14:44 -0300 (Thu, 13 Mar 2008) $
 * @since 4.0.11
 */
public class ResourcesDataType extends AbstractSourceFieldDataType
{
	protected static class ResourcesDataConverter extends AbstractConverter
	{
		@SuppressWarnings("unchecked")
		@Override
		protected <T> T doConversion(Class<T> type, Object value, Locale locale, String pattern) throws UnsupportedConversionTypeException
		{
			// the value is expected to be the schedule id
			String scheduleId = value.toString();
			
			if (type.isAssignableFrom(Data.class))
			{
				try
				{
					ITransactionHibernate transactionHibernate = (ITransactionHibernate)PortalTransactionFactory.getCurrentTransaction();
					Session session = transactionHibernate.getSession();
					Schedule schedule = (Schedule)session.get(Schedule.class, scheduleId);
					
					Collection<Resource> resources = schedule.getResources();
					return (T) new Data(resources);
					
				}
				catch (DaoException e) 
				{
					throw new ConversionException (e);
				}
			}
			if (type.isAssignableFrom(String.class))
				return (T)scheduleId;
			else
				throw new UnsupportedConversionTypeException();
		}	
	}

	
	/**
	 * Data object for a field with data type Resources.
	 * @since 4.0.11
	 */
	public static class Data implements IRenderable
	{
		private final Collection<Resource> resources;

		public Data(Collection<Resource> resources)
		{
			this.resources = resources;
		}
		
		public String getRenderData(IRenderer renderer) throws PortalException
		{
			StringBuilder value = new StringBuilder(1000);
			value.append("<value>");
			value.append(XmlUtil.encodeXml(getDisplayString(renderer)));
			value.append("</value>");
			value.append("<resources>");
			for (Resource resource: resources)
			{
				value.append("<resource id=\"" + XmlUtil.encodeXml(resource.getId()) + "\">");
				value.append("<name>");
					value.append(XmlUtil.encodeXml(resource.getName()));
				value.append("</name>");
				value.append("</resource>");
			}
			value.append("</resources>");
			return value.toString();
		}

		/**
		 * Returns the display string, as defined in {@link ResourceDataType.Data#getDisplayString(IRenderer)},
		 * of each Resource in this Resources data, separated by comma.
		 * @since 4.0.11
		 */
		public String getDisplayString(IRenderer renderer) throws PortalException
		{
			StringBuilder value = new StringBuilder(100);
			for (Resource resource: resources)
			{
				if (value.length() > 0)
					value.append(", ");
				value.append(resource.getName());
			}
			return value.toString();
		}		
	}
	
	@Override
	public String getId()
	{
		return getClass().getName();
	}
	
	@Override
	public String getQueryDataType()
	{
		return QueryFieldTypes.GUID;
	}

	@Override
	protected IConverter createConverter()
	{
		return new ResourcesDataConverter();
	}

	@Override
	public Class<?> getValueClass()
	{
		return Data.class;
	}
}
